package javabase.demo03;

import java.util.concurrent.*;

public class SynchronizerPractice {
    public static void main(String[] args) throws InterruptedException {
        // 1. CountDownLatch
        demonstrateCountDownLatch();

        // 2. CyclicBarrier
        demonstrateCyclicBarrier();

        // 3. Semaphore
        demonstrateSemaphore();

        // 4. Exchanger
        demonstrateExchanger();

        // 5. Phaser
        demonstratePhaser();
    }

    private static void demonstrateCountDownLatch() throws InterruptedException {
        System.out.println("\n=== CountDownLatch ===");

        int workerCount = 3;
        CountDownLatch startSignal = new CountDownLatch(1);
        CountDownLatch doneSignal = new CountDownLatch(workerCount);

        for (int i = 0; i < workerCount; i++) {
            final int workerId = i;
            new Thread(() -> {
                try {
                    System.out.println("工人" + workerId + "等待开工");
                    startSignal.await(); // 等待开工信号

                    System.out.println("工人" + workerId + "开始工作");
                    Thread.sleep(1000 + workerId * 500); // 模拟工作

                    System.out.println("工人" + workerId + "完成工作");
                    doneSignal.countDown(); // 完成工作
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }

        Thread.sleep(1000); // 准备时间
        System.out.println("经理发出开工信号");
        startSignal.countDown(); // 发出开工信号

        doneSignal.await(); // 等待所有工人完成
        System.out.println("所有工人已完成工作，经理开始验收");
    }

    private static void demonstrateCyclicBarrier() {
        System.out.println("\n=== CyclicBarrier ===");

        int threadCount = 3;
        CyclicBarrier barrier = new CyclicBarrier(threadCount, () -> {
            System.out.println("所有线程已到达屏障，执行屏障操作");
        });

        for (int i = 0; i < threadCount; i++) {
            final int threadId = i;
            new Thread(() -> {
                try {
                    System.out.println("线程" + threadId + "开始第一阶段");
                    Thread.sleep(1000 + threadId * 500);
                    System.out.println("线程" + threadId + "到达屏障，等待其他线程");
                    barrier.await();

                    System.out.println("线程" + threadId + "开始第二阶段");
                    Thread.sleep(1000 + threadId * 500);
                    System.out.println("线程" + threadId + "再次到达屏障，等待其他线程");
                    barrier.await();

                    System.out.println("线程" + threadId + "完成所有工作");
                } catch (InterruptedException |  BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }

    private static void demonstrateSemaphore() {
        System.out.println("\n=== Semaphore ===");

        int resourceCount = 2;
        Semaphore semaphore = new Semaphore(resourceCount);

        for (int i = 0; i < 5; i++) {
            final int threadId = i;
            new Thread(() -> {
                try {
                    System.out.println("线程" + threadId + "尝试获取资源");
                    semaphore.acquire();

                    System.out.println("线程" + threadId + "获取到资源，开始使用");
                    Thread.sleep(2000); // 模拟使用资源

                    System.out.println("线程" + threadId + "释放资源");
                    semaphore.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }

    private static void demonstrateExchanger() {
        System.out.println("\n=== Exchanger ===");

        Exchanger<String> exchanger = new Exchanger<>();

        // 生产者线程
        new Thread(() -> {
            try {
                String data = "生产的数据";
                System.out.println("生产者准备交换: " + data);
                Thread.sleep(1000);

                String received = exchanger.exchange(data);
                System.out.println("生产者收到: " + received);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        // 消费者线程
        new Thread(() -> {
            try {
                String data = "消费的数据";
                System.out.println("消费者准备交换: " + data);
                Thread.sleep(2000);

                String received = exchanger.exchange(data);
                System.out.println("消费者收到: " + received);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }

    private static void demonstratePhaser() {
        System.out.println("\n=== Phaser ===");

        Phaser phaser = new Phaser(1); // 主线程注册

        for (int i = 0; i < 3; i++) {
            phaser.register(); // 注册新线程
            final int threadId = i;
            new Thread(() -> {
                System.out.println("线程" + threadId + "到达阶段1");
                phaser.arriveAndAwaitAdvance(); // 等待所有线程到达

                System.out.println("线程" + threadId + "到达阶段2");
                phaser.arriveAndAwaitAdvance(); // 等待所有线程到达

                System.out.println("线程" + threadId + "完成");
                phaser.arriveAndDeregister(); // 完成并注销
            }).start();
        }

        // 主线程等待所有阶段完成
        phaser.arriveAndAwaitAdvance();
        System.out.println("阶段1完成");

        phaser.arriveAndAwaitAdvance();
        System.out.println("阶段2完成");

        phaser.arriveAndDeregister();
        System.out.println("所有阶段完成");
    }
}
